
// ===============================================================================================================
// -*- C++ -*-
//
// Game.hpp - Game class. Encapsulates the game logic. Demonstrates the use of the Template Method Design pattern.
//
// Copyright (c) 2011 Guilherme R. Lampert
// guilherme.ronaldo.lampert@gmail.com
//
// This code is licenced under the MIT license.
//
// This software is provided "as is" without express or implied
// warranties. You may freely copy and compile this source into
// applications you distribute provided that the copyright text
// above is included in the resulting source code.
//
// ===============================================================================================================

#ifndef __GAME_HPP__
#define __GAME_HPP__

// Local includes
#include <Common.hpp>
#include <Renderer.hpp>
#include <FmodSystem.hpp>

#include <Math.hpp>
#include <Matrix4x4.hpp>
#include <FireEffect.hpp>

#include <Player.hpp>
#include <Enemy.hpp>
#include <Billboard.hpp>

#include <GameLevel.hpp>
#include <ProceduralTerrain.hpp>

///
/// Game -- Abstract class that encapsulates most of the game logic.
/// Demonstrates the use of the Template Method Design pattern.
///
class Game {

public:

	// Template Methods:

	/// Initialize the game.
	bool Initialize(void);

	/// Update the game timer and render one frame.
	void UpdateAndRender(void);

	/// Cleanup and exit.
	void Quit(void);

	// Public Interface:

	/// Default constructor
	Game(void);

	/// Virtual destructor.
	virtual ~Game(void);

	/// Return the number of players.
	inline size_t GetNumPlayers(void) const { return (numPlayers); };

	/// Get a player instance.
	inline Player * GetPlayer(size_t i) const { return (players[i]); };

	/// Return the number of levels.
	inline size_t GetNumLevels(void) const { return (numLevels); };

	/// Get a game level instance.
	inline GameLevel * GetGameLevel(size_t i) const { return (levels[i]); };

protected:

	/*
	 * The following methods are implemeted by a specific game
	 * and are called by the template methods of this class.
	 * Deriving classes are free to implemet them in any way they see fit.
	 */

	virtual bool InitRenderingSystem(void) = 0;

	virtual bool InitSoundSystem(void) = 0;

	virtual bool LoadGameData(void) = 0;

	virtual void UpdateFrame(float elapsedTime) = 0;

	virtual void RenderFrame(void) = 0;

	virtual void TermRenderingSystem(void) = 0;

	virtual void TermSoundSystem(void) = 0;

	virtual void FreeGameData(void) = 0;

protected:

	// Game Data:

	size_t numPlayers; ///< Number of players; May be a multiplayer game
	Player ** players; ///< Game players

	size_t numLevels;    ///< Number of levels in the game
	GameLevel ** levels; ///< Game levels

	float currentTime, lastTime; ///< Time counters (Game clock)
};

// ===============================================================================================================

///
/// Implements the Game interface.
///
class FPS_GameDemo : public Game {

public:

	// Public Interface:

	FPS_GameDemo(void);

protected:

	// Game Methods:

	virtual bool InitRenderingSystem(void);
	virtual bool InitSoundSystem(void);
	virtual bool LoadGameData(void);

	virtual void UpdateFrame(float elapsedTime);
	virtual void RenderFrame(void);

	virtual void TermRenderingSystem(void);
	virtual void TermSoundSystem(void);
	virtual void FreeGameData(void);

private:

	// Game Data:

	FMOD::Sound * sndTrack;      ///< Background music
	FMOD::Sound * sndAmmoPickup; ///< Ammo pickup sound effect
	float prcLoaded;             ///< Percentage of the game loaded. From 0 to 1
	float elapsedTime;           ///< Game timer

	// Other game specific stuff
	Texture * groundNmap;
	Texture * HellknightNmap;
	ShaderProgram * normalMapShader;
};

#endif // __GAME_HPP__